﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Threading;
namespace Shape
{
	class Shapelib
	{
		static int i=1; 
		static string SourceResult;
		public	static int filecount = 0;
		static Thread dthread = new Thread(new ThreadStart(deletefile));
		public static void deletefile() {
			Filesys.deletespecifile("c:\\", "*.shp");
		}
		public static void ShapeMerge(string[] files,string path){
		filecount=	files.Length;
				//首先两个两个的合并，然后把结果文件路径存放到path里面
			//当string[]里面只有两个文件的时候停止 
		List<string> filelist = new List<string>();
				int counter =0;
			/*	while (files.Length>counter+2)
				{
					filelist.Add(ShapeMergeTwo(files[counter],files[counter+1]));
					counter++;
				}
				files = filelist.ToArray();*/
				Form1.progressBar1.Maximum = files.Length;
				Form1.progressBar1.Minimum = 0;
			while (files.Length!=counter+1)
			{
				Form1.progressBar1.Value = counter + 2;
				files[counter+1]=ShapeMergeTwo(files[counter],files[counter+1]);
				counter++;
				
				//迭代会有效率问题
			}
			//拷贝最后一个文件
			File.Copy("c:\\"+(i-1)+".shp",path,true);
			
			//dthread.Start();
			MessageBox.Show("OKAY");
			///下面句子非线程安全
			//Filesys.deletespecifile("c:\\", "*.shp");
		}


		public static string ShapeMergeTwo(string SourceOne,string SourceTwo)
        {
			 SourceResult = "c:\\"+i+".shp"; 
            //读shap文件                      
            //打开文件1，对该文件具有读权限 
            FileStream fs1 = new FileStream(SourceOne, FileMode.Open, FileAccess.Read);
            //以二进制方式读文件 
            //创建一个二进制数据流读入器，和打开的文件关联 
            BinaryReader br1 = new BinaryReader(fs1);

            FileStream fs2 = new FileStream(SourceTwo, FileMode.Open, FileAccess.Read);
            BinaryReader br2 = new BinaryReader(fs2);

            //以写的方式创建文件3，并将合并的文件头数据写回第三个文件
            FileStream fs3 = new FileStream(SourceResult, FileMode.Create, FileAccess.ReadWrite);
            BinaryWriter bw = new BinaryWriter(fs3);

            //读取文件头（前100个字节）            
            int filecode_1 = br1.ReadInt32();//便于合并，没有转换
            int unused1_1 = br1.ReadInt32();
            int unused2_1 = br1.ReadInt32();
            int unused3_1 = br1.ReadInt32();
            int unused4_1 = br1.ReadInt32();
            int unused5_1 = br1.ReadInt32();
            int fileLength_1 = ReadUsingBigEndian(br1);//便于计算总长度
            int Version_1 = br1.ReadInt32();   //小端模式存的可以直接读
            int ShapeType_1 = br1.ReadInt32();
            double Xmin_1 = br1.ReadDouble();
            double Ymin_1 = br1.ReadDouble();
            double Xmax_1 = br1.ReadDouble();
            double Ymax_1 = br1.ReadDouble();
            double Zmin_1 = br1.ReadDouble();
            double Zmax_1 = br1.ReadDouble();
            double Mmin_1 = br1.ReadDouble();
            double Mmax_1 = br1.ReadDouble();
            //MessageBox.Show(filecode_1.ToString());

            //读取文件头（前100个字节）
            int filecode_2 = ReadUsingBigEndian(br2);
            int unused1_2 = ReadUsingBigEndian(br2);
            int unused2_2 = ReadUsingBigEndian(br2);
            int unused3_2 = ReadUsingBigEndian(br2);
            int unused4_2 = ReadUsingBigEndian(br2);
            int unused5_2 = ReadUsingBigEndian(br2);
            int fileLength_2 = ReadUsingBigEndian(br2);
            int Version_2 = br2.ReadInt32();   //小端模式存的可以直接读
            int ShapeType_2 = br2.ReadInt32();
            double Xmin_2 = br2.ReadDouble();
            double Ymin_2 = br2.ReadDouble();
            double Xmax_2 = br2.ReadDouble();
            double Ymax_2 = br2.ReadDouble();
            double Zmin_2 = br2.ReadDouble();
            double Zmax_2 = br2.ReadDouble();
            double Mmin_2 = br2.ReadDouble();
            double Mmax_2 = br2.ReadDouble();

            //合并文件1和文件2的头，形成文件3的头的变量
            int filecode_3 = filecode_1;//不变 文件1和文件2中相同的变量值不变 
            int unused1_3 = unused1_1;
            int unused2_3 = unused2_1;
            int unused3_3 = unused3_1;
            int unused4_3 = unused4_1;
            int unused5_3 = unused5_1;
            int fileLength_3 = fileLength_1 + fileLength_2 - 50;// 两个文件长度相加，减去重复的头部大小50个字。因为有100个字节（16位）
            int Version_3 = Version_1;//不变 
            int ShapeType_3 = ShapeType_1;//不变 
            //比较两个文件中的最小和最大，都取最值
            double Xmin_3 = Min(Xmin_1, Xmin_2);
            double Ymin_3 = Min(Ymin_1, Ymin_2);
            double Xmax_3 = Max(Xmax_1, Xmax_2);
            double Ymax_3 = Max(Ymax_1, Ymax_2);
            double Zmin_3 = Zmin_1;//不变 
            double Zmax_3 = Zmax_1;//不变 
            double Mmin_3 = Mmin_1;//不变 
            double Mmax_3 = Mmax_1;//不变

            //将文件头写入文件3           
            bw.Write(filecode_3);
            bw.Write(unused1_3);
            bw.Write(unused2_3);
            bw.Write(unused3_3);
            bw.Write(unused4_3);
            bw.Write(unused5_3);
            bw.Write(WriteUsingBigEndian(fileLength_3));
            bw.Write(Version_3);
            bw.Write(ShapeType_3);
            bw.Write(Xmin_3);
            bw.Write(Ymin_3);
            bw.Write(Xmax_3);
            bw.Write(Ymax_3);
            bw.Write(Zmin_3);
            bw.Write(Zmax_3);
            bw.Write(Mmin_3);
            bw.Write(Mmax_3);

            //分别将文件1、2的记录逐条写入文件3。
            //每条记录包含记录头和记录内容。头为8个字节，为4个字，内容长度以字计算，所以记录长度为（4+内容长度）×16位=（4+内容长度）×2 字节
            //超过当前记录长度读取下一个记录
            //如果读取记录时，文件流位置超过文件大小，则停止读取
            //写入文件3时，需要改变的是文件2 记录的编号 必须知道文件1 最后一个编号 将其加上文件2的编号 得到文件三的编号每条记录的总长度=4+记录内容长读*2
            int ij = 0;//用来记录文件内容的记录总条数
            int length1 = 100; //记录开始的位置（因为文件头为100字节）

            while (fs3.Position < fileLength_3 * 2)
            {
                while (fs1.Position < fileLength_1 * 2)
                {
                    ++ij;
                    //记录头
                    int recordnum = ReadUsingBigEndian(br1);//记录号
                    bw.Write(WriteUsingBigEndian(recordnum));//直接写到文件3

                    int ContentLength = ReadUsingBigEndian(br1);//记录长度
                    bw.Write(WriteUsingBigEndian(ContentLength));//长度写到文件3

                    length1 += (4 + ContentLength) * 2;

                    while (fs1.Position < length1)//一直读记录内容，并写入
                    {
                        bw.Write(br1.ReadInt32());
                    }
                }

                int length2 = 100;
                while (fs2.Position < fileLength_2 * 2)
                {

                    //记录头
                    int recordnum = ReadUsingBigEndian(br2);
                    bw.Write(WriteUsingBigEndian(ij + recordnum));//记录号写到文件3,续文件1的记录

                    int ContentLength = ReadUsingBigEndian(br2);//记录长度
                    bw.Write(WriteUsingBigEndian(ContentLength));//长度写到文件3

                    length2 += (4 + ContentLength) * 2;

                    while (fs2.Position < length2)//一直读记录内容，并写入
                    {
                        bw.Write(br2.ReadInt32());
                    }
                }

            }
            bw.Close();
			i++;
			ij++;
			return SourceResult;
        }

        static int ReadUsingBigEndian(BinaryReader br)  //因为有大端模式的，所以在读的时候需要转换
        {
            byte[] bytes = br.ReadBytes(4);
            Array.Reverse(bytes);  //调整
            return BitConverter.ToInt32(bytes, 0);

        }

        static int WriteUsingBigEndian(int a)
        {
            byte[] bytes = BitConverter.GetBytes(a);
            Array.Reverse(bytes);
            return BitConverter.ToInt32(bytes, 0);

        }

        static double Max(double a, double b)
        {
            if (a > b)
                return a;
            else return b;
        }

        static double Min(double a, double b)
        {
            if (a < b)
                return a;

            else return b;
        }


    }




	}
	

